/*	T-MATS -- sp2tc_TMATS.c */

/* Stream 1 Name: N2, O2, AR, */
/* Stream 1 Species: 0.754700, 0.232000, 0.012800, */
/* Stream 2 Name: CH2, CH, */
/* Stream 2 Species: 0.922189, 0.077811, */

#include <stdio.h>
#include <stdlib.h>
#include "simstruc.h"
#include <math.h>
double sp2tc(double Entropy, double Pressure, double FAR)
{
    double tg; 
    int interpErr = 0;
    double zi, yi, xi;
	double inc_X, inc_Y, inc_Z;
	int ii, jj, kk;
	int i, j, k;
	int Lxy;
	double v000, v100, v010, v001, v101, v011, v110, v111;
	double P;
	double xx, yy, zz;
	
	int errValue = 0;
    /*generate vector length constants */
const int Lx = 8;
const int Ly = 18;
const int Lz = 6;

/* X or Pressure axis definition */
const double X[8] = {2,102,202,302,402,502,602,702};

/* Y or Temperature axis definition */
const double Y[18] = {500,700,900,1100,1300,1500,1700,1900,2100,2300,2500,2700
,2900,3100,3300,3500,3700,3900};

/* Z or fractional axis definition */
const double Z[6] = {0.000000,0.010000,0.020000,0.030000,0.040000,0.050000};

/* M or 3D lookup table of S: X,Y,Z */
const double M[864] = {1.758735,1.489133,1.442279,1.414704,1.395091,1.379858,1.367402,1.356865   /* entries 1,1,1 to 8,1,1 */
,1.839660,1.570057,1.523204,1.495628,1.476016,1.460783,1.448327,1.437790   /* entries 1,2,1 to 8,2,1 */
,1.900988,1.631385,1.584532,1.556956,1.537344,1.522111,1.509655,1.499117   /* entries 1,3,1 to 8,3,1 */
,1.950887,1.681284,1.634431,1.606855,1.587243,1.572010,1.559554,1.549017   /* entries 1,4,1 to 8,4,1 */
,1.993379,1.723777,1.676924,1.649348,1.629736,1.614503,1.602047,1.591510   /* entries 1,5,1 to 8,5,1 */
,2.030700,1.761098,1.714245,1.686669,1.667057,1.651825,1.639369,1.628831   /* entries 1,6,1 to 8,6,1 */
,2.064161,1.794559,1.747707,1.720131,1.700519,1.685287,1.672831,1.662294   /* entries 1,7,1 to 8,7,1 */
,2.094536,1.824935,1.778082,1.750507,1.730895,1.715663,1.703207,1.692670   /* entries 1,8,1 to 8,8,1 */
,2.122343,1.852742,1.805890,1.778315,1.758703,1.743471,1.731015,1.720478   /* entries 1,9,1 to 8,9,1 */
,2.148029,1.878428,1.831576,1.804002,1.784390,1.769158,1.756702,1.746166   /* entries 1,10,1 to 8,10,1 */
,2.171943,1.902342,1.855491,1.827916,1.808305,1.793073,1.780618,1.770081   /* entries 1,11,1 to 8,11,1 */
,2.194365,1.924759,1.877908,1.850333,1.830722,1.815490,1.803035,1.792498   /* entries 1,12,1 to 8,12,1 */
,2.215521,1.945898,1.899046,1.871472,1.851860,1.836629,1.824173,1.813637   /* entries 1,13,1 to 8,13,1 */
,2.235614,1.965939,1.919084,1.891509,1.871897,1.856665,1.844210,1.833673   /* entries 1,14,1 to 8,14,1 */
,2.254840,1.985029,1.938169,1.910591,1.890977,1.875744,1.863288,1.852751   /* entries 1,15,1 to 8,15,1 */
,2.273420,2.003299,1.956424,1.928840,1.909223,1.893987,1.881529,1.870991   /* entries 1,16,1 to 8,16,1 */
,2.291627,2.020866,1.973961,1.946363,1.926738,1.911498,1.899036,1.888494   /* entries 1,17,1 to 8,17,1 */
,2.309815,2.037845,1.990883,1.963260,1.943619,1.928368,1.915899,1.905351   /* entries 1,18,1 to 8,18,1 */

,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000   /* entries 1,1,2 to 8,1,2 */
,1.849695,1.580105,1.533254,1.505679,1.486068,1.470836,1.458380,1.447843   /* entries 1,2,2 to 8,2,2 */
,1.911735,1.642145,1.595294,1.567720,1.548108,1.532876,1.520421,1.509884   /* entries 1,3,2 to 8,3,2 */
,1.962292,1.692702,1.645851,1.618277,1.598665,1.583433,1.570978,1.560441   /* entries 1,4,2 to 8,4,2 */
,2.005391,1.735801,1.688951,1.661376,1.641765,1.626533,1.614077,1.603541   /* entries 1,5,2 to 8,5,2 */
,2.043275,1.773685,1.726834,1.699260,1.679649,1.664417,1.651962,1.641425   /* entries 1,6,2 to 8,6,2 */
,2.077263,1.807674,1.760824,1.733249,1.713638,1.698406,1.685951,1.675414   /* entries 1,7,2 to 8,7,2 */
,2.108138,1.838549,1.791699,1.764125,1.744513,1.729282,1.716827,1.706290   /* entries 1,8,2 to 8,8,2 */
,2.136421,1.866831,1.819981,1.792407,1.772796,1.757565,1.745110,1.734573   /* entries 1,9,2 to 8,9,2 */
,2.162562,1.892969,1.846119,1.818545,1.798934,1.783703,1.771248,1.760711   /* entries 1,10,2 to 8,10,2 */
,2.186915,1.917314,1.870463,1.842889,1.823277,1.808046,1.795591,1.785054   /* entries 1,11,2 to 8,11,2 */
,2.209770,1.940142,1.893290,1.865715,1.846103,1.830871,1.818416,1.807879   /* entries 1,12,2 to 8,12,2 */
,2.231372,1.961682,1.914824,1.887247,1.867634,1.852401,1.839945,1.829407   /* entries 1,13,2 to 8,13,2 */
,2.251952,1.982120,1.935252,1.907670,1.888053,1.872818,1.860360,1.849822   /* entries 1,14,2 to 8,14,2 */
,2.271752,2.001619,1.954731,1.927139,1.907517,1.892277,1.879816,1.869275   /* entries 1,15,2 to 8,15,2 */
,2.291060,2.020328,1.973402,1.945791,1.926158,1.910910,1.898443,1.887897   /* entries 1,16,2 to 8,16,2 */
,2.310247,2.038386,1.991393,1.963750,1.944097,1.928835,1.916357,1.905802   /* entries 1,17,2 to 8,17,2 */
,2.329810,2.055938,2.008831,1.981134,1.961447,1.946162,1.933667,1.923098   /* entries 1,18,2 to 8,18,2 */

,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000   /* entries 1,1,3 to 8,1,3 */
,1.855439,1.585861,1.539012,1.511439,1.491828,1.476597,1.464142,1.453606   /* entries 1,2,3 to 8,2,3 */
,1.918192,1.648614,1.601765,1.574192,1.554581,1.539350,1.526895,1.516359   /* entries 1,3,3 to 8,3,3 */
,1.969407,1.699829,1.652981,1.625407,1.605797,1.590566,1.578111,1.567574   /* entries 1,4,3 to 8,4,3 */
,2.013112,1.743535,1.696686,1.669113,1.649502,1.634271,1.621816,1.611280   /* entries 1,5,3 to 8,5,3 */
,2.051558,1.781981,1.735132,1.707559,1.687949,1.672718,1.660263,1.649727   /* entries 1,6,3 to 8,6,3 */
,2.086074,1.816497,1.769649,1.742076,1.722465,1.707235,1.694780,1.684243   /* entries 1,7,3 to 8,7,3 */
,2.117448,1.847871,1.801023,1.773450,1.753840,1.738609,1.726154,1.715618   /* entries 1,8,3 to 8,8,3 */
,2.146206,1.876628,1.829780,1.802207,1.782597,1.767366,1.754911,1.744375   /* entries 1,9,3 to 8,9,3 */
,2.172797,1.903216,1.856367,1.828795,1.809184,1.793954,1.781499,1.770963   /* entries 1,10,3 to 8,10,3 */
,2.197579,1.927986,1.881136,1.853563,1.833952,1.818722,1.806267,1.795731   /* entries 1,11,3 to 8,11,3 */
,2.220844,1.951216,1.904364,1.876790,1.857178,1.841947,1.829492,1.818955   /* entries 1,12,3 to 8,12,3 */
,2.242844,1.973136,1.926278,1.898700,1.879086,1.863854,1.851397,1.840860   /* entries 1,13,3 to 8,13,3 */
,2.263827,1.993937,1.947065,1.919481,1.899863,1.884627,1.872169,1.861630   /* entries 1,14,3 to 8,14,3 */
,2.284060,2.013788,1.966890,1.939293,1.919667,1.904425,1.891962,1.881420   /* entries 1,15,3 to 8,15,3 */
,2.303880,2.032847,1.985900,1.958279,1.938639,1.923386,1.910915,1.900366   /* entries 1,16,3 to 8,16,3 */
,2.323742,2.051269,2.004236,1.976574,1.956907,1.941637,1.929152,1.918592   /* entries 1,17,3 to 8,17,3 */
,2.344272,2.069223,2.022041,1.994309,1.974600,1.959299,1.946791,1.936213   /* entries 1,18,3 to 8,18,3 */

,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000   /* entries 1,1,4 to 8,1,4 */
,1.859201,1.589636,1.542790,1.515218,1.495608,1.480377,1.467923,1.457387   /* entries 1,2,4 to 8,2,4 */
,1.922667,1.653102,1.606255,1.578683,1.559074,1.543843,1.531389,1.520853   /* entries 1,3,4 to 8,3,4 */
,1.974540,1.704975,1.658129,1.630557,1.610947,1.595717,1.583262,1.572726   /* entries 1,4,4 to 8,4,4 */
,2.018852,1.749287,1.702441,1.674869,1.655259,1.640029,1.627574,1.617038   /* entries 1,5,4 to 8,5,4 */
,2.057860,1.788296,1.741449,1.713878,1.694268,1.679038,1.666583,1.656047   /* entries 1,6,4 to 8,6,4 */
,2.092904,1.823339,1.776493,1.748921,1.729312,1.714082,1.701627,1.691091   /* entries 1,7,4 to 8,7,4 */
,2.124777,1.855212,1.808366,1.780795,1.761185,1.745955,1.733501,1.722965   /* entries 1,8,4 to 8,8,4 */
,2.154008,1.884443,1.837597,1.810025,1.790415,1.775185,1.762731,1.752195   /* entries 1,9,4 to 8,9,4 */
,2.181049,1.911479,1.864632,1.837061,1.817451,1.802221,1.789767,1.779231   /* entries 1,10,4 to 8,10,4 */
,2.206256,1.936671,1.889824,1.862251,1.842642,1.827411,1.814957,1.804421   /* entries 1,11,4 to 8,11,4 */
,2.229923,1.960299,1.913449,1.885875,1.866264,1.851033,1.838578,1.828042   /* entries 1,12,4 to 8,12,4 */
,2.252309,1.982592,1.935734,1.908156,1.888543,1.873310,1.860854,1.850317   /* entries 1,13,4 to 8,13,4 */
,2.273674,2.003744,1.956870,1.929285,1.909667,1.894431,1.881972,1.871432   /* entries 1,14,4 to 8,14,4 */
,2.294315,2.023930,1.977026,1.949425,1.929798,1.914554,1.902090,1.891547   /* entries 1,15,4 to 8,15,4 */
,2.314621,2.043317,1.996354,1.968726,1.949081,1.933825,1.921352,1.910801   /* entries 1,16,4 to 8,16,4 */
,2.335143,2.062078,2.015010,1.987332,1.967656,1.952378,1.939888,1.929324   /* entries 1,17,4 to 8,17,4 */
,2.356657,2.080403,2.033155,2.005391,1.985662,1.970348,1.957830,1.947243   /* entries 1,18,4 to 8,18,4 */

,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000   /* entries 1,1,5 to 8,1,5 */
,1.861338,1.591786,1.544942,1.517371,1.497762,1.482532,1.470079,1.459543   /* entries 1,2,5 to 8,2,5 */
,1.925517,1.655964,1.609120,1.581549,1.561940,1.546711,1.534257,1.523721   /* entries 1,3,5 to 8,3,5 */
,1.978048,1.708496,1.661651,1.634081,1.614472,1.599242,1.586789,1.576253   /* entries 1,4,5 to 8,4,5 */
,2.022966,1.753414,1.706570,1.678999,1.659390,1.644161,1.631707,1.621171   /* entries 1,5,5 to 8,5,5 */
,2.062537,1.792985,1.746141,1.718571,1.698962,1.683732,1.671278,1.660743   /* entries 1,6,5 to 8,6,5 */
,2.098108,1.828556,1.781712,1.754141,1.734533,1.719303,1.706849,1.696314   /* entries 1,7,5 to 8,7,5 */
,2.130479,1.860927,1.814083,1.786513,1.766904,1.751675,1.739221,1.728686   /* entries 1,8,5 to 8,8,5 */
,2.160183,1.890630,1.843786,1.816216,1.796607,1.781378,1.768924,1.758389   /* entries 1,9,5 to 8,9,5 */
,2.187671,1.918113,1.871268,1.843698,1.824089,1.808859,1.796406,1.785870   /* entries 1,10,5 to 8,10,5 */
,2.213299,1.943725,1.896879,1.869308,1.849699,1.834469,1.822015,1.811479   /* entries 1,11,5 to 8,11,5 */
,2.237361,1.967745,1.920896,1.893323,1.873712,1.858482,1.846027,1.835491   /* entries 1,12,5 to 8,12,5 */
,2.260123,1.990402,1.943545,1.915968,1.896355,1.881122,1.868667,1.858129   /* entries 1,13,5 to 8,13,5 */
,2.281858,2.011894,1.965019,1.937434,1.917815,1.902579,1.890120,1.879581   /* entries 1,14,5 to 8,14,5 */
,2.302898,2.032400,1.985490,1.957888,1.938258,1.923014,1.910550,1.900006   /* entries 1,15,5 to 8,15,5 */
,2.323703,2.052099,2.005121,1.977486,1.957836,1.942578,1.930102,1.919550   /* entries 1,16,5 to 8,16,5 */
,2.344952,2.071182,2.024079,1.996385,1.976699,1.961415,1.948919,1.938351   /* entries 1,17,5 to 8,17,5 */
,2.367610,2.089875,2.042550,2.014753,1.995003,1.979675,1.967146,1.956551   /* entries 1,18,5 to 8,18,5 */

,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000   /* entries 1,1,6 to 8,1,6 */
,1.861798,1.592258,1.545416,1.517847,1.498239,1.483010,1.470557,1.460022   /* entries 1,2,6 to 8,2,6 */
,1.926689,1.657149,1.610307,1.582738,1.563130,1.547901,1.535448,1.524913   /* entries 1,3,6 to 8,3,6 */
,1.979879,1.710339,1.663497,1.635928,1.616320,1.601091,1.588637,1.578102   /* entries 1,4,6 to 8,4,6 */
,2.025403,1.755864,1.709022,1.681452,1.661844,1.646615,1.634162,1.623627   /* entries 1,5,6 to 8,5,6 */
,2.065537,1.795997,1.749155,1.721586,1.701978,1.686749,1.674296,1.663761   /* entries 1,6,6 to 8,6,6 */
,2.101634,1.832095,1.785253,1.757683,1.738076,1.722847,1.710394,1.699859   /* entries 1,7,6 to 8,7,6 */
,2.134503,1.864964,1.818122,1.790553,1.770945,1.755716,1.743263,1.732728   /* entries 1,8,6 to 8,8,6 */
,2.164678,1.895138,1.848296,1.820726,1.801118,1.785890,1.773436,1.762902   /* entries 1,9,6 to 8,9,6 */
,2.192609,1.923063,1.876221,1.848651,1.829043,1.813814,1.801361,1.790826   /* entries 1,10,6 to 8,10,6 */
,2.218651,1.949089,1.902245,1.874675,1.855067,1.839837,1.827384,1.816849   /* entries 1,11,6 to 8,11,6 */
,2.243099,1.973492,1.926645,1.899073,1.879463,1.864233,1.851779,1.841243   /* entries 1,12,6 to 8,12,6 */
,2.266224,1.996501,1.949645,1.922069,1.902457,1.887225,1.874769,1.864233   /* entries 1,13,6 to 8,13,6 */
,2.288322,2.018316,1.971441,1.943856,1.924238,1.909001,1.896543,1.886003   /* entries 1,14,6 to 8,14,6 */
,2.309780,2.039125,1.992209,1.964604,1.944974,1.929729,1.917264,1.906719   /* entries 1,15,6 to 8,15,6 */
,2.331177,2.059121,2.012124,1.984480,1.964826,1.949564,1.937086,1.926532   /* entries 1,16,6 to 8,16,6 */
,2.353394,2.078529,2.031376,2.003659,1.983960,1.968667,1.956165,1.945592   /* entries 1,17,6 to 8,17,6 */
,2.377659,2.097628,2.050191,2.022343,2.002563,1.987214,1.974670,1.964063   /* entries 1,18,6 to 8,18,6 */

};

double Sg1, Tg1, dTdS, Tfin;
int IterMax = 10;
 int iter = 0;
 double Sg = 1e3;
 double Stol = 1e-4;

/* Pressure [psia]*/
xi = Pressure;
/* Temperature guess [degR]*/
yi = 1000;
/* FAR */
zi = FAR;
while ((fabs(Entropy - P) >= Stol && iter < IterMax) || (iter < 2)){

	/*********************************/
	/*check for out of bounds errors */
	/*********************************/

	/* Check to see if zi is outside of X vector */
	if (xi < X[0]){
        errValue = 1;
		xi = X[0];
    }
    else if (xi > X[Lx-1]){
        errValue = 1;
		xi = X[Lx-1];
    }
	else if (!(xi >= X[0]))
	{
		// xi must be NaN to have failed by < X[0]  and >= X[0]
		errValue = 1;
		xi = X[0];
	}

	/* Check to see if zi is outside of Y vector */
	if (yi < Y[0]){
        errValue = 1;
		yi = Y[0];
    }
    else if (yi > Y[Ly-1]){
        errValue = 1;
		yi = Y[Ly-1];
    }
	else if (!(yi >= Y[0]))
	{
		// yi must be NaN to have failed by < Y[0]  and >= Y[0]
		errValue = 1;
		yi = Y[0];
	}

	/* Check to see if zi is outside of Z vector */
	if (zi < Z[0]){
        errValue = 1;
		zi = Z[0];
    }
    else if (zi > Z[Lz-1]){
        errValue = 1;
		zi = Z[Lz-1];
    }
	else if (!(zi >= Z[0]))
	{
		// zi must be NaN to have failed by < Z[0]  and >= Z[0]
		errValue = 1;
		zi = Z[0];
	}


	/* Search for starting point. Point 0,0,0 of a bounding cube  */

	/*JL: */
	/* Faster search routine which assumes equal spacing in X, Y, Z
	inc_X = (X[Lx-1]-X[0])/(Lx-1);
	inc_Y = (Y[Ly-1]-Y[0])/(Ly-1);
	inc_Z = (Z[Lz-1]-Z[0])/(Lz-1);
	ii = floor((xi-X[0])/inc_X);
	jj = floor((yi-Y[0])/inc_Y);
	kk = floor((zi-Z[0])/inc_Z); */

	/*JL: Brute force search routine */
	i = Lx-2;
	j = Ly-2;
	k = Lz-2;
	while (i >= 0){
		if (xi >= X[i]){
			ii = i;
			break;
		}
		else
			i = i - 1;
    }

	while (j >= 0){
		if (yi >= Y[j]){
			jj = j;
			break;
		}
		else
			j = j - 1;
    }

	while (k >= 0){
		if (zi >= Z[k]){
			kk = k;
			break;
		}
		else
			k = k - 1;
    }

	/*-------------------------------------------------------------- */

	Lxy = Lx*Ly;

	/* JL
	Find the values at the vertices of the bounding cube

	Assume M is structured as follows:
	First increment x values with others constant
	Then increment y once, and then increment x values
	When done with y values, finally increment z once
	Repeat until z is done */
	v000 = M[kk*Lxy + jj*Lx + ii];
	v100 = M[kk*Lxy + jj*Lx + (ii+1)];
	v010 = M[kk*Lxy + (jj+1)*Lx + ii];
	v001 = M[(kk+1)*Lxy + jj*Lx + ii];
	v101 = M[(kk+1)*Lxy + jj*Lx + (ii+1)];
	v011 = M[(kk+1)*Lxy + (jj+1)*Lx + ii];
	v110 = M[kk*Lxy + (jj+1)*Lx + (ii+1)];
	v111 = M[(kk+1)*Lxy + (jj+1)*Lx + (ii+1)];

	/* Normalize/translate coords xi,yi,zi so that they go from 0 to 1 within bounding cube */
	xx = (xi-X[ii])/(X[ii+1]-X[ii]);
	yy = (yi-Y[jj])/(Y[jj+1]-Y[jj]);
	zz = (zi-Z[kk])/(Z[kk+1]-Z[kk]);
	/* 3D interpolation */
	P = v000*(1-xx)*(1-yy)*(1-zz) + v100*xx*(1-yy)*(1-zz) + v010*(1-xx)*yy*(1-zz) + v001*(1-xx)*(1-yy)*zz + v101*xx*(1-yy)*zz + v011*(1-xx)*yy*zz + v110*xx*yy*(1-zz) + v111*xx*yy*zz;

        if (errValue == 1)
            printf("Warning in Pressure and Temperature to Entropy lookup, lookup tables should be expanded\n");

    errValue = 0;
if (iter==0){
 Sg1 = P;
Tg1 = yi;
yi = Tg1+50;
}
else{
dTdS = (yi-Tg1)/(P-Sg1);
Tg1 = yi;
Sg1 = P;
yi = Tg1 + (Entropy-P)*dTdS;

if (yi > Y[Ly-1]){
yi = Y[Ly-1];}
if (yi < Y[0]){
yi = Y[0];}
else if (!(yi >= Y[0])){
yi = Y[0];}

}
++iter;
}
if (iter >= IterMax)
printf("Warning in Entropy and Pressure to Temperature. Correct temperature could not be found\n");
Tfin = yi;
return Tfin;
 }